package com.logistic.server.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.logistic.server.common.constant.RedisConst;
import com.logistic.server.common.enums.IsDelEnum;
import com.logistic.server.common.exception.BaseException;
import com.logistic.server.common.utils.RedisUtils;
import com.logistic.server.common.utils.SecurityUtils;
import com.logistic.server.entity.common.LoginBody;
import com.logistic.server.entity.common.WebUserToken;
import com.logistic.server.entity.common.WxOpenData;
import com.logistic.server.entity.dto.RouterDto;
import com.logistic.server.entity.pojo.SysMenu;
import com.logistic.server.entity.pojo.SysUser;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 登录校验方法
 *
 * @author swen
 */
@Service
public class ISysLoginService {

    @Resource
    private ISysUserService userService;

    @Resource
    private ISysDeptService deptService;

    @Resource
    private ISysMenuService menuService;

    @Resource
    private ISysPermissionService permissionService;

    @Resource
    private RedisUtils redis;

    @Resource
    private WxMaService wxMaService;

    /**
     * 12小时后过期
     */
    private final static long EXPIRE = 12 * 60 * 60;

    /**
     * 校验账号密码
     * @param loginBody 账号密码
     * @return WebUserToken
     */
    public WebUserToken login(LoginBody loginBody) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysUser::getUserName, loginBody.getUsername());
        SysUser user = userService.selectUserByUserName(loginBody.getUsername());
        if (user == null) {
            throw new BaseException("账号密码错误");
        }
        if ("1".equals(user.getStatus())) {
            throw new BaseException("用户已被锁定");
        }
        if (!SecurityUtils.matchesPassword(user.getPassword(), SecurityUtils.password(loginBody.getPassword()))) {
            throw new BaseException("密码错误");
        }
        return this.createToken(user);
    }


    /**
     * 微信登录
     * @param code 微信登录的code
     * @return user
     * @throws WxErrorException e
     */
    public WebUserToken login(String code) throws WxErrorException {
        SysUser user;
        WxMaJscode2SessionResult jscode2session = wxMaService.getUserService().getSessionInfo(code);
        String openid = jscode2session.getOpenid();
        String unionid = jscode2session.getUnionid();
        String sessionKey = jscode2session.getSessionKey();
        user = userService.findByOpenId(openid);
        if (ObjectUtil.isEmpty(user)) {
            user = SysUser.builder().build();
            user.setCreateTime(new Date());
            user.setCreateBy("admin");
            user.setUserName(String.valueOf(System.currentTimeMillis()));
            user.setDelFlag(IsDelEnum.FALSE.getValue());
            user.setOpenid(openid);
            user.setDeptId(200L);
            //新增用户
            userService.save(user);
        }
        return this.createToken(user);
    }

    /**
     * 获取微信用户信息
     * @param wxOpenData
     * @return user
     */
    public SysUser bind(WxOpenData wxOpenData) {
        WxMaUserInfo wxMaUserInfo = wxMaService.getUserService().getUserInfo(wxOpenData.getSessionKey(), wxOpenData.getEncryptedData(), wxOpenData.getIv());
        SysUser user = userService.selectUserById(wxOpenData.getWechatUserId());
        user.setNickName(wxMaUserInfo.getNickName());
        user.setSex("1".equals(wxMaUserInfo.getGender()) ? "男" : "2".equals(wxMaUserInfo.getGender()) ? "女" : "未知");
        user.setCity(wxMaUserInfo.getCity());
        user.setProvince(wxMaUserInfo.getProvince());
        user.setCountry(wxMaUserInfo.getCountry());
        user.setAvatar(wxMaUserInfo.getAvatarUrl());
        userService.updateUser(user);
        return user;
    }

    /**
     * 缓存用户信息并且生成token
     * @param user 用户信息
     * @return WebUserToken
     */
    public WebUserToken createToken(SysUser user) {
        // 生成token
        String token = IdUtil.fastSimpleUUID();
        // 返回用户信息用于缓存
        WebUserToken webUserToken = BeanUtil.copyProperties(user, WebUserToken.class);
        webUserToken.setAccessToken(token);
        webUserToken.setExpiredTime(EXPIRE);
        webUserToken.setRoles(permissionService.getRolePermission(webUserToken.getUserId()));
        webUserToken.setPermissions(permissionService.getMenuPermission(webUserToken.getUserId()));
        webUserToken.setDept(deptService.selectDeptById(webUserToken.getDeptId()));
        redis.set(RedisConst.ACCESS_TOKEN + token, webUserToken, EXPIRE);
        return webUserToken;
    }

    /**
     * 刷新token
     * @param webUserToken 用户信息
     */
    public void refreshToken(WebUserToken webUserToken) {
        webUserToken.setExpiredTime(EXPIRE);
        redis.set(RedisConst.ACCESS_TOKEN + webUserToken.getAccessToken(), webUserToken, EXPIRE);
    }

    /**
     * 退出登陆
     * @param webUserToken 用户信息
     */
    public void Logout(WebUserToken webUserToken) {
        if (ObjectUtil.isNotEmpty(webUserToken)) {
            redis.delete(RedisConst.ACCESS_TOKEN + webUserToken.getAccessToken());
        }
    }

    /**
     * 获取用户菜单
     * @param webUserToken 用户信息
     * @return routers
     */
    public List<RouterDto> getRouters(WebUserToken webUserToken) {
        List<SysMenu> menus;
        if (SysUser.isAdmin(webUserToken.getUserId())) {
            menus = menuService.selectMenuTreeAll();
        } else {
            menus = menuService.selectMenuTreeByUserId(webUserToken.getUserId());
        }
        menus = menuService.getChildPerms(menus, 0);
        return menuService.buildMenus(menus);
    }

}
